package com.sxhuayuan.parking.socket.handler;

import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.alibaba.fastjson.JSON;
import com.sxhuayuan.parking.entity.ParkingLot;
import com.sxhuayuan.parking.exception.NettyException;
import com.sxhuayuan.parking.service.ParkingLotService;
import com.sxhuayuan.parking.socket.AuthorizationToken;
import com.sxhuayuan.parking.socket.ChannelGroupPool;
import com.sxhuayuan.parking.utils.SettingUtils;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;

/**
 * MyWebSocketHandler WebSocket处理器，处理websocket连接相关
 */
@Sharable
public class ParkingLotInterfaceHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

	Logger log = LoggerFactory.getLogger(ParkingLotInterfaceHandler.class);

	static final String CONN_SUCCESS_MSG = "{\"result\":\"success\"}";

	private ChannelGroupPool channelGroupPool;

	@Autowired
	ParkingLotService lotService;

	public ParkingLotInterfaceHandler(ChannelGroupPool channelGroupPool) {
		super();
		this.channelGroupPool = channelGroupPool;
	}

	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		log.debug("与客户端建立连接，通道开启！id={}", ctx.channel());
	}

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		log.debug("与客户端断开连接，通道关闭！");
		// 添加到channelGroup 通道组
		channelGroupPool.removeChannel(ctx.channel());
	}

	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
		// 首次连接是FullHttpRequest，处理身份校验
		if (null != msg && msg instanceof FullHttpRequest) {
			FullHttpRequest request = (FullHttpRequest) msg;
			String uri = request.uri();

			Map<String, String> paramMap = getUrlParams(uri);
			String json = JSON.toJSONString(paramMap);
			log.debug("接收到的参数是：{}", json);
			// 如果url包含参数，需要处理
			if (uri.contains("?")) {
				String newUri = uri.substring(0, uri.indexOf("?"));
				log.debug(newUri);
				request.setUri(newUri);
			}

			AuthorizationToken token = JSON.parseObject(json, AuthorizationToken.class);
			Channel channel = ctx.channel();
			if (token != null) {
				if (!SettingUtils.get().getIsDebug()) {
					ParkingLot lot = lotService.findBySn(token.getUser());
					if (lot == null) {
						log.debug("user不存在，断开连接...");
						channel.disconnect();
						return;
					}
					if (Math.abs(System.currentTimeMillis() - token.getTimestamp()) > 5 * 60 * 1000) {
						log.debug("时间戳过期，断开连接...");
						channel.disconnect();
						return;
					}
					if (!token.isSignValid(lot.getApiKey())) {
						log.debug("签名错误，断开连接...");
						channel.disconnect();
						return;
					}
				}
			} else {
				log.debug("未授权连接，断开连接...");
				channel.disconnect();
				return;
			}
			// 添加到channelGroup通道组
			String username = paramMap.get("user");
			channelGroupPool.addChannel(username, channel);
			final String username2 = username;
			new Thread() {
				public void run() {
					try {
						channelGroupPool.sendMsg(username2, CONN_SUCCESS_MSG);
					} catch (NettyException e) {
						log.error("", e);
					}
				};
			}.start();
		}
		super.channelRead(ctx, msg);
	}

	@Override
	protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame frame) throws Exception {
		log.debug("收到客户端数据：id={}, user={}, txt={}", ctx.channel().id(), channelGroupPool.findUsername(ctx.channel().id()), frame.text());
		String resp = frame.text();
		try {
			String uid = JSON.parseObject(resp).getString("uid");
			if (uid != null) {
				log.debug("[{}][{}]通知返回notify", Thread.currentThread().getName(), uid);
				channelGroupPool.notifyResponse(uid, resp);
			}
		} catch (Exception e) {
		}
	}

	private static Map<String, String> getUrlParams(String url) {
		Map<String, String> map = new HashMap<>();
		url = url.replace("?", ";");
		if (!url.contains(";")) {
			return map;
		}
		if (url.split(";").length > 0) {
			String[] arr = url.split(";")[1].split("&");
			for (String s : arr) {
				String key = s.split("=")[0];
				String value = s.split("=")[1];
				map.put(key, value);
			}
			return map;

		} else {
			return map;
		}
	}
}